#include "Object.h"
#include "teapot.h"
#include "Vehicle.h"
#include "Vector2D.h"


Object :: Object ( unsigned int shaderProgramID, float size, float x, float y, float z, float gx, float gy, float gz, color colors, int textureIndex, bool visible ) :
_shaderProgramID ( shaderProgramID ),
_size   	 ( size ),
_z      	 ( z ),
_gx     	 ( gx ),
_gy     	 ( gy ),
_gz     	 ( gz ),
_colors 	 ( colors ),
_textureIndex( textureIndex ),
_visible	 ( visible )
{
	_vehicle.setPos( Vector2D( x, y ) );
	_vertexHandle = glGetAttribLocation(_shaderProgramID,
			"vertexPosition");
	_normalHandle = glGetAttribLocation(_shaderProgramID,
			"vertexNormal");
	_textureCoordHandle  = glGetAttribLocation(_shaderProgramID,
			"vertexTexCoord");
	_mvpMatrixHandle = glGetUniformLocation(_shaderProgramID,
			"modelViewProjectionMatrix");
}

Object :: Object ( unsigned int shaderProgramID, float size, float x ,float y, float z, float gx, float gy, float gz, float red, float green, float blue, float alpha, int textureIndex, bool visible ) :
						_shaderProgramID ( shaderProgramID ),
						_size   ( size ),
						_z      ( z ),
						_gx     ( gx ),
						_gy     ( gy ),
						_gz     ( gz ),
						_textureIndex( textureIndex ),
						_visible( visible )
{
	_vehicle.setPos( Vector2D( x, y ) );
	_colors.red   = red;
	_colors.green = green;
	_colors.blue  = blue;
	_colors.alpha = alpha;
	_vertexHandle = glGetAttribLocation(_shaderProgramID,
			"vertexPosition");
	_normalHandle        = glGetAttribLocation(_shaderProgramID,
			"vertexNormal");
	_textureCoordHandle = glGetAttribLocation(_shaderProgramID,
			"vertexTexCoord");
	_mvpMatrixHandle = glGetUniformLocation(_shaderProgramID,
			"modelViewProjectionMatrix");
}

void Object :: draw ( QCAR::Matrix44F *modelViewMatrix, QCAR::Matrix44F *projectionMatrix, Texture** textures)
{
	/*
	glColor4f   ( _colors.red, _colors.green, _colors.blue , _colors.alpha );
    glTranslatef( _vehicle.getPos().x, _vehicle.getPos().y, _z );
    glRotatef   ( _gx, 1.0, 0.0, 0.0 );
    glRotatef   ( _gy, 0.0, 1.0, 0.0 );
    glRotatef   ( _gz + -atan2(_vehicle.getHeading().x, _vehicle.getHeading().y), 0.0, 0.0, 1.0 );
	 */
	float m[16];
	SampleUtils::multiplyMatrix(&(projectionMatrix->data[0]),
				&(modelViewMatrix->data[0]) ,
				&(m[0]));
	QCAR::Matrix44F transform = SampleMath::Matrix44FIdentity();
	float* transformPtr = &transform.data[0];


	QCAR::Matrix44F modelViewProjection,objectMatrix;
	float angle = -atan2(_vehicle.getCurrVel().x,_vehicle.getCurrVel().y);
	float dangle = angle*180.0/3.1416 + _gz;

	SampleUtils::translatePoseMatrix(_vehicle.getPos().x, _vehicle.getPos().y, _z,transformPtr);
	SampleUtils::rotatePoseMatrix( dangle, 0.0, 0.0, 1.0, transformPtr );
	SampleUtils::scalePoseMatrix(_size, _size, _size,transformPtr);



	SampleUtils::multiplyMatrix(&modelViewMatrix->data[0], transformPtr, &objectMatrix.data[0]);
	SampleUtils::multiplyMatrix(&projectionMatrix->data[0], &objectMatrix.data[0], &modelViewProjection.data[0]);
	//SampleUtils::multiplyMatrix(&(projectionMatrix->data[0]),transformPtr ,&(modelViewProjection.data[0]));

	glUseProgram(_shaderProgramID);
	drawObject  ( &modelViewProjection, textures );
	/*    glRotatef   ( _gz*-1, 0.0, 0.0, 1.0 );
    glRotatef   ( _gy*-1, 0.0, 1.0, 0.0 );
    glRotatef   ( _gx*-1, 1.0, 0.0, 0.0 );
    glTranslatef( _vehicle.getPos().x*-1, _vehicle.getPos().y*-1, _z *-1 );*/

	/*SampleUtils::rotatePoseMatrix( (dangle)*-1, 0.0, 0.0, 1.0, &(modelViewMatrix->data[0]) );
	SampleUtils::scalePoseMatrix((_size)*-1, (_size)*-1, (_size)*-1,&(modelViewMatrix->data[0]));
	SampleUtils::translatePoseMatrix(-(_vehicle.getPos().x), -(_vehicle.getPos().y), _size,
			&(modelViewMatrix->data[0]));
			*/
	glUniformMatrix4fv(_mvpMatrixHandle, 1, GL_FALSE,
			(GLfloat*)&(m[0]) );
}

void Object :: drawObject(  QCAR::Matrix44F *modelViewProjection, Texture** )
{
}


TeaPot :: TeaPot( unsigned int shaderProgramID, float size, float x ,float y, float z, float gx, float gy, float gz, color colors, int textureIndex, bool visible ) : Object ( shaderProgramID, size, x ,y, z, gx, gy, gz, colors, textureIndex, visible )
{
}

TeaPot :: TeaPot( unsigned int shaderProgramID, float size, float x ,float y, float z, float gx, float gy, float gz, float red, float green, float blue, float alpha, int textureIndex, bool visible ) : Object ( shaderProgramID, size, x ,y, z, gx, gy, gz, red, green, blue, alpha, textureIndex, visible )
{
}

void TeaPot :: drawObject( QCAR::Matrix44F *modelViewProjection, Texture** textures )
{
	const Texture* const thisTexture = textures[_textureIndex];


	glVertexAttribPointer(_vertexHandle, 3, GL_FLOAT, GL_FALSE, 0,
			(const GLvoid*) &teapotVertices[0]);
	glVertexAttribPointer(_normalHandle, 3, GL_FLOAT, GL_FALSE, 0,
			(const GLvoid*) &teapotNormals[0]);
	glVertexAttribPointer(_textureCoordHandle, 2, GL_FLOAT, GL_FALSE, 0,
			(const GLvoid*) &teapotTexCoords[0]);

	glEnableVertexAttribArray(_vertexHandle);
	glEnableVertexAttribArray(_normalHandle);
	glEnableVertexAttribArray(_textureCoordHandle);

	glBindTexture(GL_TEXTURE_2D, thisTexture->mTextureID );
	glUniformMatrix4fv(_mvpMatrixHandle, 1, GL_FALSE,
			(GLfloat*)&(modelViewProjection->data[0]) );
	glDrawElements(GL_TRIANGLES, NUM_TEAPOT_OBJECT_INDEX, GL_UNSIGNED_SHORT,
			(const GLvoid*) &teapotIndices[0]);


	/*
	glBindTexture    ( GL_TEXTURE_2D, 1 );
	glTexCoordPointer( 2, GL_FLOAT, 0, (const GLvoid*) &teapotTexCoords[0]);
	glVertexPointer  ( 3, GL_FLOAT, 0, (const GLvoid*) &teapotVertices[0]);
	glNormalPointer  ( GL_FLOAT, 0,  (const GLvoid*) &teapotNormals[0]);
	glDrawElements   ( GL_TRIANGLES, NUM_TEAPOT_OBJECT_INDEX, GL_UNSIGNED_SHORT, (const GLvoid*) &teapotIndices[0]);
	 */
}

void Object :: setShaderProgramID( unsigned int shaderProgramID )
{
	_shaderProgramID = shaderProgramID;

	_vertexHandle        = glGetAttribLocation(_shaderProgramID,
			"vertexPosition");
	_normalHandle        = glGetAttribLocation(_shaderProgramID,
			"vertexNormal");
	_textureCoordHandle  = glGetAttribLocation(_shaderProgramID,
			"vertexTexCoord");
	_mvpMatrixHandle     = glGetUniformLocation(_shaderProgramID,
			"modelViewProjectionMatrix");
}

ObjObject :: ObjObject( unsigned int shaderProgramID, float size, float x ,float y, float z, float gx, float gy, float gz, color colors, int textureIndex, bool visible ) : Object ( shaderProgramID, size, x ,y, z, gx, gy, gz, colors, textureIndex, visible )
{
}

ObjObject :: ObjObject( unsigned int shaderProgramID, float size, float x ,float y, float z, float gx, float gy, float gz, float red, float green, float blue, float alpha, int textureIndex, bool visible ) : Object ( shaderProgramID, size, x ,y, z, gx, gy, gz, red, green, blue, alpha, textureIndex, visible )
{
}

void ObjObject :: drawObject( QCAR::Matrix44F *modelViewProjection, Texture** textures )
{
	const Texture* const thisTexture = textures[_textureIndex];


	/*glVertexAttribPointer(_vertexHandle, 3, GL_FLOAT, GL_FALSE, 0,
							  (const GLvoid*) &teapotVertices[0]);
		glVertexAttribPointer(_normalHandle, 3, GL_FLOAT, GL_FALSE, 0,
							  (const GLvoid*) &teapotNormals[0]);
		glVertexAttribPointer(_textureCoordHandle, 2, GL_FLOAT, GL_FALSE, 0,
							  (const GLvoid*) &teapotTexCoords[0]);

		glEnableVertexAttribArray(_vertexHandle);
		glEnableVertexAttribArray(_normalHandle);
		glEnableVertexAttribArray(_textureCoordHandle);*/

	glBindTexture(GL_TEXTURE_2D, thisTexture->mTextureID );
	glUniformMatrix4fv(_mvpMatrixHandle, 1, GL_FALSE,
			(GLfloat*)&(modelViewProjection->data[0]) );
	obj->draw(_vertexHandle,_normalHandle,_textureCoordHandle);

	/*
	glBindTexture    ( GL_TEXTURE_2D, 1 );
	glTexCoordPointer( 2, GL_FLOAT, 0, (const GLvoid*) &teapotTexCoords[0]);
	glVertexPointer  ( 3, GL_FLOAT, 0, (const GLvoid*) &teapotVertices[0]);
	glNormalPointer  ( GL_FLOAT, 0,  (const GLvoid*) &teapotNormals[0]);
	glDrawElements   ( GL_TRIANGLES, NUM_TEAPOT_OBJECT_INDEX, GL_UNSIGNED_SHORT, (const GLvoid*) &teapotIndices[0]);
	 */
}

bool ObjObject :: loadObjObject (string objectName)
{
	obj = loadOBJ(objectName);
	LOG("%d",obj);
	if(obj)
	{
		LOG("obj cargado");
		LOG("%d", obj->numVerts);
		LOG("%f",obj->verts[0]);
		return true;
	}
	else
	{
		LOG("obj null");
		return false;
	}
}
